import { _decorator, Label, ProgressBar, sp, Sprite, Tween, tween, v3, Vec3 } from 'cc';
import { ListRender } from '../../Basic/Component/ListRender';
import { autoComp } from '../../Basic/Manager/BaseManager';
import { ItemData } from '../Config/GlobalModel';
import { TowerItem } from './TowerItem';
import { MainModel_Ins } from './MainModel';
import { EventManager } from '../../Basic/Manager/EventManager';
import { GameEventType } from '../Config/GameEnum';

const { ccclass, property } = _decorator;
@ccclass('EnemyItem')
export class EnemyItem extends ListRender {
  @autoComp(sp.Skeleton)
  spine: sp.Skeleton;

  @autoComp(ProgressBar)
  bar_hp: ProgressBar;
  @autoComp(Sprite)
  bar: Sprite;
  @autoComp(Label)
  lab_bar: Label;
  data: ItemData;

  gridPos: number[] = [];

  movePath: number[][] = [];
  moveLock: boolean = true;

  curState: string = '';
  protected onLoad(): void {
    this.spine.setCompleteListener(this.onSpineComplete.bind(this));
  }

  dataChanged(): void {
    this.refreshHp();
    this.playAni('Walk');
  }

  refreshHp() {
    this.lab_bar.string = `${this.data.hp}/${this.data.hpMax}`;
    Tween.stopAllByTarget(this.bar_hp);
    let rate = this.data.hp / this.data.hpMax;
    rate = rate <= 0 ? 0 : rate;
    rate = rate >= 1 ? 1 : rate;
    this.bar_hp.node.active = true;
    tween(this.bar_hp)
      .to(0.2, { progress: rate })
      .delay(0.2)
      .call(() => {
        this.bar_hp.node.active = false;
      })
      .start();
  }

  playAni(state: string) {
    if (this.curState === state) return;
    this.curState = state;
    let loop = false;
    switch (this.curState) {
      case 'Idle':
      case 'Walk':
        loop = true;
        break;
    }
    this.spine.setAnimation(0, this.curState, loop);
  }

  onSpineComplete(t: sp.spine.TrackEntry) {
    switch (t.animation.name) {
      case 'Attack':
      case 'Attack3':
        this.playAni('Idle');
        break;
    }
  }

  setMovePath(path: number[][]) {
    path.length > 0 && path.pop();
    this.movePath.length = 0;
    this.movePath.push(...path);
  }

  protected update(dt: number): void {
    if (this.IsDeah) return;
    if (this.movePath.length > 0) {
      this.playAni('Walk');
      // 移动
      const lPos = this.node.getPosition().clone();
      const movePos = this.movePath[0];
      const targetPos = MainModel_Ins.basePanel.getPosVec3(movePos);
      const moveDir = new Vec3(targetPos.x - lPos.x, targetPos.y - lPos.y);
      const length = moveDir.length();
      if (length <= 10) {
        this.gridPos = this.movePath.shift();
        // if (this.movePath.length <= 0) this.playAni('Idle');
      }
      const dir = moveDir.normalize();
      this.node.setPosition(lPos.add(v3(dir.x * 100 * dt, dir.y * 100 * dt)));
      this.node.setSiblingIndex(-Math.floor(this.node.getPosition().y));
      this.spine.node.setScale(dir.x >= 0 ? 1 : -1, 1);
    } else if (this.atkTarget !== null) {
      this.atkCount += dt;
      if (this.atkCount >= this.atkSpace) {
        this.atkCount = 0;
        this.attack();
      }
    }
  }

  get IsDeah() {
    return this.data.hp <= 0;
  }

  hirt(value: number) {
    this.data.hp -= value;
    this.data.hp = this.data.hp <= 0 ? 0 : this.data.hp;
    this.refreshHp();
    if (this.IsDeah) this.die();
  }

  private atkTarget: TowerItem = null;
  private atkSpace: number = 1;
  private atkCount: number = 0;
  /** 检测攻击对象 */
  checkAtkTarget(targetArr: TowerItem[]) {
    let target = null;
    let minDis = 9999;
    const enemyPos = this.node.getPosition().clone();
    targetArr.forEach((tower) => {
      const towerPos = tower.node.getPosition().clone();
      const dis = new Vec3(towerPos.x - enemyPos.x, towerPos.y - enemyPos.y);
      if (dis.length() <= minDis) {
        minDis = dis.length();
        target = tower;
      }
    });
    this.atkTarget = target;

    if (this.atkTarget !== null && this.movePath.length <= 0) {
      this.setMovePath(MainModel_Ins.basePanel.getMovePath(this.gridPos, this.atkTarget.gridPos));
    }
  }

  attack() {
    const atkTarget = this.atkTarget;
    const atkValue = this.data.atk;
    // this.playAni(Math.random() > 0.5 ? 'Attack' : 'Attack3');
    if (atkTarget.IsDeah || atkTarget.node.parent === null) this.atkTarget = null;
    else {
      MainModel_Ins.basePanel.createEnemyButtle(atkTarget.node.getPosition());
      atkTarget.hirt(atkValue);
    }
    // EventManager.Ins().emit(GameEventType.MAIN_CREATE_BUTTLE, bPos, ePos, () => {
    //   if (atkTarget.IsDeah) return;
    //   else atkTarget.hirt(atkValue);
    // });
  }

  die() {
    EventManager.Ins().emit(GameEventType.MAIN_RECOVER, this.node);
    console.log('enemy die');
    MainModel_Ins.basePanel.enemyCount--;
    MainModel_Ins.basePanel.enemyCount = MainModel_Ins.basePanel.enemyCount <= 0 ? 0 : MainModel_Ins.basePanel.enemyCount;
  }
}
